//循环队列！
public class MyBlockingQueue {
    private int[] nums = new int[100];
    volatile private int head = 0;
    volatile private int tail = 0;
    volatile private int size = 0;

    //入队列
    synchronized public void put(int elem) throws InterruptedException{
        //如果队列满了，阻塞等待
        if(size == nums.length){
            this.wait();
        }
        //如果队列未满，则可以继续添加
        nums[tail] = elem;
        tail++;
        //检查一下元素添加的位置是否未数组的最后一个
        if(tail == nums.length){
            tail = 0;
        }
        size++;
        //如果别的线程要取元素，发现数组为空，wait阻塞等待了，以下代码唤醒！
        //如果并没有别的线程阻塞等待，那么以下代码也没有任何副作用！
        this.notify();
    }

    //出队列
    synchronized public int take() throws InterruptedException{
        //如果队列为空，则阻塞等待
        if(size == 0){
            this.wait();
        }
        //如果队列不为空，那么就可以放心取元素了
        int value = nums[head];
        head++;
        //检查head是否已经来到数组的最后一个下标+1
        if(head == nums.length){
            head = 0;
        }
        size--;
        this.notify();
        return value;
    }
}
